#include "stdafx.h"
#include "GameState.h"
#include "RenderSystem.h"
#include "ResourceManager.h"
#include "InputManager.h"
#include "EntityManager.h"
#include "SceneManager.h"
#include "EntityFactory.h"
#include "Camera.h"


GameState::GameState(
		const EType& type,
		RenderSystem* render_system,
		ResourceManager* resource_manager,
		InputManager* input_manager,
		EntityManager* entity_manager,
		SceneManager* scene_manager,
		EntityFactory* entity_factory,
		GuiManager* gui_manager,
		Camera* camera) 
		: State(type)
{
	m_render_system = render_system;
	m_resource_manager = resource_manager;
	m_input_manager = input_manager;
	m_entity_manager = entity_manager;
	m_scene_manager = scene_manager;
	m_entity_factory = entity_factory;
	m_gui_manager = gui_manager;
	m_camera = camera;
}


GameState::~GameState(void)
{
}


bool GameState::Init()
{
	// skydome
	Skydome *skydome=new Skydome;
	skydome->Init(m_render_system);
	m_scene_manager->SetSkydome(skydome);

	// heightmap
	Heightmap *heightmap=new Heightmap;
	heightmap->Create(m_render_system,"../data/texture/heightmap2.tga");
	m_scene_manager->SetHeightmap(heightmap);

	m_widget = new Gui::Button;
	m_widget->SetWidth(200.0f);
	m_widget->SetHeight(50.0f);
	m_widget->SetX(50.0f);
	m_widget->SetY(50.0f);

	m_gui_manager->AttachWidget(m_widget);

	//m_widget2 = new Gui::Button;
	//m_widget->SetWidth(50.0f);
	//m_widget->SetHeight(50.0f);
	//m_widget->SetX(200.0f);
	//m_widget->SetY(200.0f);
	//m_gui_manager->AttachWidget(m_widget2);

	//Entity* ent;
	//for (int z = 0; z < 10; z++)
	//{
	//	for (int x = 0; x < 10; x++)
	//	{
	//		ent = m_entity_factory->Create(EEntityType::Basic_Tower);
	//		ent->SetPosition(Vector3(x * 5.0f, 1.0f, z * 5.0f));
	//		m_entity_manager->AddEntity(ent);
	//	}
	//}

	m_terrain_vertices = heightmap->GetVertices();

	return true;
}
void GameState::Shut()
{
}

void GameState::Update(float deltatime)
{
	m_entity_manager->Update(deltatime);

	if (m_input_manager->ButtonPressed(MB_Left))
		Pick(m_input_manager->m_mouse.m_position.x, m_input_manager->m_mouse.m_position.y);

	m_gui_manager->Update();
}

void GameState::Render()
{
	m_render_system->Clear();

	m_scene_manager->Render(m_render_system, m_camera);
	m_gui_manager->Render();

	m_render_system->Present();
}

void GameState::Pick(float x, float y)
{
	using namespace DirectX;

	Mat4 proj = m_camera->GetProj();
	Mat4 view = m_camera->GetView();
	Mat4 world = XMMatrixIdentity();

	XMVECTOR origin = XMVectorSet(x, y, 0.0f, 1.0f);
	origin = XMVector3Unproject(origin, 0.0f, 0.0f, 1440.0f, 900.0f, 0.0f, 1.0f, proj, view, world);
	
	XMVECTOR camera_pos(XMLoadFloat3(&m_camera->GetPosition()));

	XMVECTOR direction(origin - camera_pos);
	direction = XMVector3Normalize(direction);

	bool found = false;

	for (int y = 0; y < 32 - 1; y++)
	{
		for (int x = 0; x < 32 - 1; x++)
		{
			int topLeft = (32 * y) + x;
			int topRight = (32 * y) + (x + 1);
			int botLeft = (32 * (y + 1)) + x;
			int botRight = (32 * (y + 1)) + (x + 1);

			Heightmap::Vertex A = m_terrain_vertices[topLeft];
			Heightmap::Vertex B = m_terrain_vertices[topRight];
			Heightmap::Vertex C = m_terrain_vertices[botLeft];
			Heightmap::Vertex D = m_terrain_vertices[botRight];

			Vec3 v0pos = Vec3(A.position.x, A.position.y, A.position.z);
			XMVECTOR v0 = XMLoadFloat3(&v0pos);

			Vec3 v1pos = Vec3(B.position.x, B.position.y, B.position.z);
			XMVECTOR v1 = XMLoadFloat3(&v1pos);

			Vec3 v2pos = Vec3(C.position.x, C.position.y, C.position.z);
			XMVECTOR v2 = XMLoadFloat3(&v2pos);

			Vec3 v3pos = Vec3(D.position.x, D.position.y, D.position.z);
			XMVECTOR v3 = XMLoadFloat3(&v3pos);

			float d = 0.0f;
			if (TriangleTests::Intersects(origin, direction, v0, v1, v2, d) || TriangleTests::Intersects(origin, direction, v2, v1, v3, d))
			{
				// hit_position = place in world where the ray intersected triangle
				XMVECTOR hit_position = origin + direction * d;
				Vec3 h_p;
				XMStoreFloat3(&h_p, hit_position);
				
				Entity* ent = m_entity_factory->Create(EEntityType::N64_Logo);
				ent->SetPosition(Vector3(h_p.x, h_p.y + 2.0f, h_p.z));

				m_entity_manager->AddEntity(ent);

				found = true;
				break;
			}
		}
		if (found)
			break;
	}

}